package com.fingard.dsp.bank.directbank.ccb41;

import jcifs.smb.SmbFile;

import java.io.*;

import com.fingard.dsp.bank.directbank.DirectBase;
import com.fingard.io.FileHelper;
import com.fingard.net.ITcpClient;
import com.fingard.net.TcpPortClient;
import com.fingard.net.TcpReceiver;
import com.fingard.text.StringHelper;
import com.fingard.xml.XmlTextWriter;

/**
 * Created by F on 2018/7/3.
 */
public class CCB41Base extends DirectBase implements ITcpClient {

    @Override
    public void getContentLength(TcpReceiver p_receiver) throws Exception {}

    protected String getCharset() {
        return getBankConfig().getCharset("GBK");
    }

    protected void writeCommonHeader(XmlTextWriter xmlWriter, CCB41Header p_bankHeader) throws Exception {
        if (StringHelper.isNullOrEmpty(p_bankHeader.tranId)) {
            throw new Exception("未赋值tranId");
        }
        if (StringHelper.isNullOrEmpty(p_bankHeader.compId)) {
            throw new Exception("未赋值compId");
        }
        if (StringHelper.isNullOrEmpty(p_bankHeader.seqNo)) {
            throw new Exception("未赋值seqNo");
        }
        xmlWriter.writeStartElement("Root");
        xmlWriter.writeStartElement("Head");
        xmlWriter.writeElementString("Tranid",p_bankHeader.tranId,true);//交易号
        xmlWriter.writeElementString("Trandate",p_bankHeader.tranDate,true);//交易日期
        xmlWriter.writeElementString("Compid", p_bankHeader.compId,true);//项目编号
        xmlWriter.writeElementString("Seqno", p_bankHeader.seqNo,true);//授权申请流水号
        xmlWriter.writeEndElement();
    }

    protected String[] sendToBank(String p_reqStr) throws Exception {

        String[] retStr = new String[]{"", ""};
        //报文明文必须压缩成一行
        p_reqStr = p_reqStr.replaceAll("\r|\n","");
        WriteBankLogLn("提交银行报文的明文："+p_reqStr);
        byte[] tmpBytesBody = Des3.encryptMode(p_reqStr.getBytes(getCharset()),bankFront.keyID);
        WriteBankLogLn("2.提交银行的地址：" + bankFront.serverIP + ":" + bankFront.serverPort);
        //发送银行前置
        TcpPortClient tmpClient = new TcpPortClient(bankFront.serverIP, Integer.parseInt(bankFront.serverPort), this);
        String readTimeOut = getBankConfig().getValueAsString("readTimeOut");
        if(StringHelper.isNullOrEmpty(readTimeOut)){
            readTimeOut="120";
        }
        tmpClient.timeoutMil = Integer.valueOf(readTimeOut)*1000;
        TcpReceiver tmpReceiver = tmpClient.sendMessage(tmpBytesBody);
        retStr[0] = tmpReceiver.connState;
        if(retStr[0].length()>0){
            retStr[1] = tmpReceiver.connMsg;
            return retStr;
        }
        if (tmpReceiver.recBytes != null) {
            byte[] bytes = new byte[tmpReceiver.readedLength];
            if((tmpReceiver.readedLength%8)!=0){
                WriteBankLogLn("银行返回报文的长度："+tmpReceiver.readedLength);
                throw new Exception("银行返回数据异常");
            }
            System.arraycopy(tmpReceiver.recBytes,0,bytes,0,tmpReceiver.readedLength);
            tmpReceiver.recBytes = Des3.decryptMode(bytes,bankFront.keyID);
            retStr[1] = new String(tmpReceiver.recBytes,getCharset());
            WriteBankLogStep3(retStr[1]);
        } else {
            retStr[1] = tmpReceiver.getConnMsg();
        }
        return retStr;
    }
    protected String[] sendEleFileToBank(String fullFilePath) throws Exception {

        String[] retStr = new String[]{"", ""};
        File file = new File(fullFilePath);
        byte[] sourceZip = FileHelper.toByteArray(fullFilePath);
        byte[] encrypt = Des3.encryptMode(sourceZip,bankFront.keyID);
        String header = String.format("%010d",encrypt.length)+String.format("%100s",file.getName());
        WriteBankLogLn("上传文件的报文头："+header);
        String prot = getBankConfig().getValueAsString("uploadFilePort");
        WriteBankLogLn("2.提交银行的地址：" + bankFront.serverIP + ":" + prot);
        byte[] headers = header.getBytes();
        byte[] reqByte = new byte[headers.length+encrypt.length];
        System.arraycopy(headers,0,reqByte,0,headers.length);
        System.arraycopy(encrypt,0,reqByte,headers.length,encrypt.length);
        //发送银行前置
        TcpPortClient tmpClient = new TcpPortClient(bankFront.serverIP, Integer.parseInt(prot), this);
        TcpReceiver tmpReceiver = tmpClient.sendMessage(reqByte);
        retStr[0] = tmpReceiver.connState;
        if(retStr[0].length()>0){
            retStr[1] = tmpReceiver.connMsg;
            WriteBankLogLn(tmpReceiver.connMsg);
            return retStr;
        }
        if (tmpReceiver.recBytes != null) {
            byte[] bytes = new byte[tmpReceiver.readedLength];
            if((tmpReceiver.readedLength%8)!=0){
                WriteBankLogLn("银行返回报文的长度："+tmpReceiver.readedLength);
                throw new Exception("银行返回数据异常");
            }
            System.arraycopy(tmpReceiver.recBytes,0,bytes,0,tmpReceiver.readedLength);
            tmpReceiver.recBytes = Des3.decryptMode(bytes,bankFront.keyID);
//            返回报文长度(10位,不足部分前面以0补齐)+返回码(4位)+返回信息(250位)
            int length = Integer.valueOf(new String(tmpReceiver.recBytes,0,10));
            WriteBankLogLn("银行返回报文的长度："+length);
            retStr[0] = new String(tmpReceiver.recBytes,10,4);
            retStr[1] = new String(tmpReceiver.recBytes,14,length-14,getCharset());
            WriteBankLogStep3(new String(tmpReceiver.recBytes,getCharset()));
        } else {
            retStr[1] = tmpReceiver.getConnMsg();
            WriteBankLogLn(tmpReceiver.connMsg);
        }
        return retStr;
    }

    protected String[] sendEleFileToBank(SmbFile smbFile) throws Exception {

        String[] retStr = new String[]{"", ""};
        byte[] sourceZip = toByteArray(smbFile);
        byte[] encrypt = Des3.encryptMode(sourceZip,bankFront.keyID);
        String header = String.format("%010d",encrypt.length)+String.format("%100s",smbFile.getName());
        WriteBankLogLn("上传文件的报文头："+header);
        WriteBankLogLn("2.提交银行的地址：" + bankFront.serverIP + ":" + bankFront.serverPort);
        byte[] headers = header.getBytes();
        byte[] reqByte = new byte[headers.length+encrypt.length];
        System.arraycopy(headers,0,reqByte,0,headers.length);
        System.arraycopy(encrypt,0,reqByte,headers.length,encrypt.length);
        //发送银行前置
        String prot = getBankConfig().getValueAsString("uploadFilePort");
        TcpPortClient tmpClient = new TcpPortClient(bankFront.serverIP, Integer.parseInt(prot), this);
        TcpReceiver tmpReceiver = tmpClient.sendMessage(reqByte);
        retStr[0] = tmpReceiver.connState;
        if(retStr[0].length()>0){
            retStr[1] = tmpReceiver.connMsg;
            return retStr;
        }
        if (tmpReceiver.recBytes != null) {
            byte[] bytes = new byte[tmpReceiver.readedLength];
            if((tmpReceiver.readedLength%8)!=0){
                WriteBankLogLn("银行返回报文的长度："+tmpReceiver.readedLength);
                throw new Exception("银行返回数据异常");
            }
            System.arraycopy(tmpReceiver.recBytes,0,bytes,0,tmpReceiver.readedLength);
            tmpReceiver.recBytes = Des3.decryptMode(bytes,bankFront.keyID);
//            返回报文长度(10位,不足部分前面以0补齐)+返回码(4位)+返回信息(250位)
            int length = Integer.valueOf(new String(tmpReceiver.recBytes,0,10));
            retStr[0] = new String(tmpReceiver.recBytes,10,4);
            retStr[1] = new String(tmpReceiver.recBytes,14,length-14,getCharset());
            WriteBankLogStep3(new String(tmpReceiver.recBytes,getCharset()));
        } else {
            retStr[1] = tmpReceiver.getConnMsg();
        }
        return retStr;
    }

    public static byte[] toByteArray(SmbFile smbFile) throws IOException {

        ByteArrayOutputStream bos = new ByteArrayOutputStream((int) smbFile.length());
        BufferedInputStream in = null;
        try {
            in = new BufferedInputStream(smbFile.getInputStream());
            int buf_size = 1024;
            byte[] buffer = new byte[buf_size];
            int len = 0;
            while (-1 != (len = in.read(buffer, 0, buf_size))) {
                bos.write(buffer, 0, len);
            }
            return bos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            bos.close();
        }
    }
}
